package com.cq;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.cq.pojo.ExceptionConstants;
import com.cq.pojo.Page;

import net.sf.json.JsonConfig;

/**
 * TODO controller 层通用方法
 */

public class BaseController {

	protected String deleteFunctionName = "doDelete";

	protected String insertFunctionName = "doInsert";

	protected String updateFunctionName = "doUpdate";

	protected String selectFunctionName = "doSelect";

	protected String editFunctionName = "doEdit";

	protected String addFunctionName = "doAdd";

	protected String exportFunctionName = "doExport";

	protected String importFunctionName = "doImport";

	protected final static String controllerPath = "/api/";

	protected final static String pagePath = "/page/";

	protected SimpleDateFormat date_format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	/*
	 * BASE PREFIX URL
	 */
	private final static String BASE_CONSOLE_PREFIX_URL = "console/%s";

	/**
	 * Logger
	 */
	protected Logger logger = Logger.getLogger(this.getClass());

	/*
	 * 获取页面路径
	 */
	protected final String getView(String url) {
		StringBuffer sb = new StringBuffer();
		String className = this.getClass().getSimpleName();
		String name = className.split("Controller")[0];
		String name_first = name.substring(0, 1);
		sb = sb.append(name_first.toLowerCase()).append(name.substring(1));
		String name_final = sb.toString();
		String path = name_final + "/" + url;
		return path;
	}

	protected final String getConsoleView(String viewName) {
		return String.format(BASE_CONSOLE_PREFIX_URL, viewName);
	}

	public static final JsonConfig jsonConfig = new JsonConfig();

	/**
	 * TODO 组装分页查询
	 * 
	 * @param paraMap
	 * @return
	 */
	protected Page<?> assemblePageSelect(Map<String, String> paraMap) {
		String pageNo = paraMap.get(ResultCodeConstants.PAGE_OBJECT);
		String rows = paraMap.get(ResultCodeConstants.ROWS_OBJECT);
		return assemblePageSelect(pageNo, rows);
	}

	protected Page<?> assemblePageSelect(Integer pageNo, Integer rows) {
		Page<?> page = new Page<>();
		page.setPageNo(pageNo);
		page.setPageSize(rows);
		return page;
	}

	protected Page<?> assemblePageSelect(String pageNo, String rows) {
		return assemblePageSelect(Integer.parseInt(pageNo), Integer.parseInt(rows));
	}

	/**
	 * TODO 组装非查询时返回结果格式
	 * 
	 * @param code
	 *            成功失败标识 ExceptionConstants.SUCCESS_CODE
	 *            ExceptionConstants.ERROR_CODE
	 * @param message
	 *            返回给前台的消息文本
	 * @return
	 */
	protected String assembleUnSelectResult(String code, String message) {
		JSONObject resultObj = new JSONObject();
		if (ExceptionConstants.SUCCESS_CODE.equals(code)) {
			resultObj.put("status", ExceptionConstants.SUCCESS_CODE);
			resultObj.put("message", message != null ? message : ExceptionConstants.SUCCESS_MESSAGE);
		} else {
			resultObj.put("status", ExceptionConstants.ERROR_CODE);
			resultObj.put("message", message != null ? message : ExceptionConstants.ERROR_MESSAGE);
		}
		return resultObj.toString();
	}

	/**
	 * TODO 组装查询时返回结果格式
	 * 
	 * @param obj
	 * @param page
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	protected String assemblePlatSelectResult(Pages<?> page) {
		JSONObject innerObj = new JSONObject();
		innerObj.put(ExceptionConstants.RESULT_TOTAL_CODE, page == null ? 1 : page.getTotal_page());
		innerObj.put(ExceptionConstants.RESULT_FILT_CODE, page == null ? 0 : page.getTotal_count());
		innerObj.put(ExceptionConstants.DRAW_CODE, page == null ? 0 : page.getDraw());
		if (page != null && page.getList() != null && page.getList().size() > 0
				&& page.getList() instanceof Collection) {
			innerObj.put(ExceptionConstants.RESULT_CODE, net.sf.json.JSONArray.fromObject(page.getList(), jsonConfig));
		} else {
			innerObj.put(ExceptionConstants.RESULT_CODE, net.sf.json.JSONArray.fromObject(new ArrayList(), jsonConfig));
		}
		innerObj.put(ExceptionConstants.RESULT_STATUC_CODE, ExceptionConstants.SUCCESS_CODE);
		innerObj.put(ExceptionConstants.RESULT_MSG_CODE, ExceptionConstants.SUCCESS_MESSAGE);
		return innerObj.toString();
	}

	/**
	 * TODO 组装查询时返回结果格式
	 * 
	 * @param obj
	 * @param page
	 * @return
	 */
	protected String assembleSelectResult(List<?> obj, Page<?> page) {
		JSONObject resultObj = new JSONObject();
		JSONObject innerObj = new JSONObject();
		innerObj.put("totalPages", page == null ? 1 : page.getTotalPage());
		innerObj.put("totalElements", page == null ? 0 : page.getTotalRecord());
		innerObj.put("size", page == null ? 0 : page.getPageSize());
		if (obj != null && obj instanceof Collection) {
			innerObj.put("content", net.sf.json.JSONArray.fromObject(obj, jsonConfig));
		} else {
			innerObj.put("content", net.sf.json.JSONArray.fromObject(obj, jsonConfig));
		}
		resultObj.put("message", innerObj);
		return resultObj.toString();
	}

	/**
	 * TODO 组装非查询时返回结果格式
	 * 
	 * @param succCount
	 *            成功操作的数据量（大于0说明成功）
	 * @param code
	 *            返回给前台的消息CODE
	 * @return
	 */
	protected String assembleUnSelectResult(int succCount, String code) {
		JSONObject resultObj = new JSONObject();
		if (succCount > 0) {
			resultObj.put("status", "success");
			resultObj.put("message", code != null ? code : ExceptionConstants.SUCCESS_MESSAGE);
		} else {
			resultObj.put("status", "error");
			resultObj.put("message", code == null ? ExceptionConstants.ERROR_MESSAGE : code);
		}
		return resultObj.toString();
	}

	/**
	 * TODO 组装非查询入参
	 * 
	 * @param request
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	@SuppressWarnings({ "unchecked" })
	protected Map<String, String> assembleUnSelectParam(HttpServletRequest request)
			throws UnsupportedEncodingException {
		Map<String, String> paraMap = new ConcurrentHashMap<>();
		Enumeration<String> eles = request.getParameterNames();
		while (eles.hasMoreElements()) {
			String key = null;
			try {
				key = URLDecoder.decode(eles.nextElement(), "utf-8");
				paraMap.putAll(JSON.parseObject(key, HashMap.class));
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			} catch (JSONException e) {

			}
		}
		return paraMap;
	}

	protected String getJsonString(Object data) {
		JSONObject json = new JSONObject();
		json.put("data", data);
		return json.toString();
	}

	protected String resultToJson(int succCount, String code, Object data) {
		JSONObject resultObj = new JSONObject();
		resultObj.put(ExceptionConstants.RESULT_STATUC_CODE, succCount);
		resultObj.put(ExceptionConstants.RESULT_MSG_CODE, code);
		resultObj.put("data", data);
		return resultObj.toString();
	}

	// 获取controller类名前缀（实体bean）
	protected String getBeanName() {
		String controllerName = this.getClass().getSimpleName();
		String beanName = controllerName.split("Controller")[0];
		return beanName;
	}

	// 获取controller属性名
	protected Field getControllerFields(String fieldName) {
		Field[] fields = this.getClass().getDeclaredFields();
		if (fields == null) {
			return null;
		}
		for (Field field : fields) {
			if (field.getName().equals(fieldName)) {
				return field;
			}
		}
		return null;
	}

	// 获取实体bean对象
	protected Object getBeanObject() throws Exception {
		String beforeName = getBeanName();
		String beanName = beforeName.substring(0, 1).toLowerCase() + beforeName.substring(1);
		Field field = getControllerFields(beanName);
		return field.getType().newInstance();
	}

	// 获取参数bean对象
	protected Object getParamBeanObject() throws Exception {
		String paramBeanName = ResultCodeConstants.BEAN_PARAM + getBeanName();
		Field field = getControllerFields(paramBeanName);
		return field.getType().newInstance();
	}

	// 跳转页面
	protected ModelAndView returnPage(String pageName) {
		ModelAndView view = new ModelAndView();
		view.setViewName(getView(pageName));
		return view;
	}

	/**
	 * 参数日志记录
	 * 
	 * @param request
	 * @param methodName
	 * @param paramNames
	 */
	@SuppressWarnings("rawtypes")
	protected void addRequestKeyLog(HttpServletRequest request, String methodName, String... paramNames) {
		if (logger.isDebugEnabled()) {
			logger.debug("the method is api " + methodName + "-->Start");
			if (paramNames == null || paramNames.length == 0) {
				Map parameter_map = request.getParameterMap();
				Iterator it = parameter_map.keySet().iterator();
				while (it.hasNext()) {
					String key_str = (String) it.next();
					if (StringUtils.isNotBlank(key_str) && key_str.indexOf("columns[") < 0) {
						String value_str = ((String[]) parameter_map.get(key_str))[0];
						logger.debug("this request key is " + key_str + " value is " + value_str);
					}
				}
			} else {
				for (String paramName : paramNames) {
					String KEY_VALUE = request.getParameter(paramName) == null ? "" : request.getParameter(paramName);
					logger.debug("this request key is " + paramName + " value is " + KEY_VALUE);
				}
			}
			logger.debug("*********" + methodName + "*********END");

		}
	}

	/**
	 * 
	 * @Title: doSearch
	 * @Description: 查询分页或tree型结构 或全部数据
	 * @param request
	 *            isTree为0时,isAllData为0时,返回分页;isAllData为1时,返回全部数据;isTree为1时,返回树结构
	 * @param serviceObj
	 * @return 参数说明
	 * @return String 返回类型
	 * @author yeqingchao
	 * @date 2018年1月30日 下午10:17:04
	 */
	protected String doSearch(HttpServletRequest request, Object serviceObj) {
		try {
			// 是否为debug下的日志级别
			if (logger.isDebugEnabled()) {
				addRequestKeyLog(request, this.getClass().getName(), "");
			}
			Map<String, String> paraMap = RequestToBean.assembleRequestParam(request);
			int isTree = 0;
			int isAllData = 0;
			if (StringUtils.isBlank(paraMap.get(ResultCodeConstants.ISTREENAME))) {
				isTree = 0;
			} else {
				isTree = Integer.valueOf(paraMap.get(ResultCodeConstants.ISTREENAME));
				if (isTree != 0 || isTree != 1) {
					return resultToJson(ResultCodeConstants.ERROR, "isTree取值范围[0,1]！", null);
				}
			}
			if (StringUtils.isBlank(paraMap.get(ResultCodeConstants.ISALLDATANAME))) {
				isAllData = 0;
			} else {
				isAllData = Integer.valueOf(paraMap.get(ResultCodeConstants.ISALLDATANAME));
				if (isAllData != 0 || isAllData != 1) {
					return resultToJson(ResultCodeConstants.ERROR, "isAllData取值范围[0,1]！", null);
				}
			}
			Object bean = getParamBeanObject();
			if (paraMap != null && paraMap.size() > 0) {
				bean = JSON.parseObject(JSON.toJSONString(paraMap), bean.getClass());
			}
			Map<String, Integer> map = new HashMap<String, Integer>();
			map.put(ResultCodeConstants.ISTREENAME, isTree);
			map.put(ResultCodeConstants.ISALLDATANAME, isAllData);
			if (isTree == 0) {
				if (isAllData == 0) {
					return assemblePlatSelectResult((Pages<?>) BaseUtil
							.getMethodFunction(selectFunctionName, serviceObj).invoke(serviceObj, bean, map));
				} else {
					return resultToJson(ResultCodeConstants.SUCCESS, "",
							BaseUtil.getMethodFunction(selectFunctionName, serviceObj).invoke(serviceObj, bean, map));
				}
			} else {
				return resultToJson(ResultCodeConstants.SUCCESS, "",
						BaseUtil.getMethodFunction(selectFunctionName, serviceObj).invoke(serviceObj, bean, map));
			}

		} catch (Exception e) {
			return assemblePlatSelectResult(null);
		}

	}

	/**
	 * 
	 * @Title: doInsert
	 * @Description: 新增工具类 success result {"isOk":1,"msg":"新增成功！"} error result
	 *               {"isOk":0,"msg":"新增失败！"}
	 * @param request
	 * @param serviceObj
	 * @param serviceObj
	 * @return 参数说明
	 * @return String 返回类型
	 * @author yeqingchao
	 * @date 2018年1月27日 下午10:41:44
	 */
	@SuppressWarnings("unchecked")
	protected String doInsert(HttpServletRequest request, Object serviceObj) {
		try {
//			User user = getUser(request);
			Object bean = getBeanObject();
			Map<String, Object> msgMap = null; 
//					(Map<String, Object>) getObjectBean(request, bean, user, serviceObj,
//					insertFunctionName);
			if (msgMap == null) {
				return resultToJson(ResultCodeConstants.ERROR, "新增失败！", null);
			}
			int code = (int) msgMap.get(ExceptionConstants.RESULT_STATUC_CODE);
			String msg = (String) msgMap.get(ExceptionConstants.RESULT_MSG_CODE);
			return resultToJson(code, msg, null);
		} catch (Exception e) {
			return resultToJson(ResultCodeConstants.ERROR, "新增失败！", null);
		}
	}

	/**
	 * 
	 * @Title: doUpdate
	 * @Description: 修改工具类 success result {"isOk":1,"msg":"修改成功！"} error result
	 *               {"isOk":0,"msg":"修改失败！"}
	 * @param request
	 * @param serviceObj
	 * @return 参数说明
	 * @return String 返回类型
	 * @author yeqingchao
	 * @date 2018年1月27日 下午10:44:02
	 */
	@SuppressWarnings("unchecked")
	protected String doUpdate(HttpServletRequest request, Object serviceObj) {
		try {
//			User user = getUser(request);
			Object bean = getBeanObject();
			Map<String, Object> msgMap = null;
//			(Map<String, Object>) getObjectBean(request, bean, user, serviceObj,
//					updateFunctionName);
			if (msgMap == null) {
				return resultToJson(ResultCodeConstants.ERROR, "修改失败！", null);
			}
			int code = (int) msgMap.get(ExceptionConstants.RESULT_STATUC_CODE);
			String msg = (String) msgMap.get(ExceptionConstants.RESULT_MSG_CODE);
			return resultToJson(code, msg, null);
		} catch (Exception e) {
			return resultToJson(ResultCodeConstants.ERROR, "修改失败！", null);
		}
	}

	/**
	 * 
	 * @Title: doDelete
	 * @Description: 单个删除工具类 success result {"isOk":1,"msg":"删除成功！"} error result
	 *               {"isOk":0,"msg":"删除失败！"}
	 * @param request
	 * @param serviceObj
	 * @return 参数说明
	 * @return String 返回类型
	 * @author yeqingchao
	 * @date 2018年1月26日 下午6:33:32
	 */
	@SuppressWarnings("unchecked")
	protected String doDelete(HttpServletRequest request, Object serviceObj) {
		try {
			Object bean = getParamBeanObject();
			Map<String, Object> msgMap = (Map<String, Object>) getObjectBean(request, bean, serviceObj,
					deleteFunctionName);
			if (msgMap == null) {
				return resultToJson(ResultCodeConstants.ERROR, "删除失败！", null);
			}
			int code = (int) msgMap.get(ExceptionConstants.RESULT_STATUC_CODE);
			String msg = (String) msgMap.get(ExceptionConstants.RESULT_MSG_CODE);
			return resultToJson(code, msg, null);
		} catch (Exception e) {
			return resultToJson(ResultCodeConstants.ERROR, "删除失败！", null);
		}
	}

	/**
	 * 
	 * @Title: doEdit
	 * @Description: 获取修改页面数据 success result
	 *               {"data":{"abbrevia":"AF","areaCname":"阿富汗"}} error result
	 *               {"isOk":0,"msg":"获取数据失败！"}
	 * @param request
	 * @param serviceObj
	 * @return 参数说明
	 * @return String 返回类型
	 * @author yeqingchao
	 * @date 2018年1月27日 下午10:59:31
	 */
	protected String doEdit(HttpServletRequest request, Object serviceObj) {
		try {
			Object bean = getParamBeanObject();
			return resultToJson(ResultCodeConstants.SUCCESS, "",
					getObjectBean(request, bean, serviceObj, editFunctionName));
		} catch (Exception e) {
			return resultToJson(ResultCodeConstants.ERROR, "获取数据失败！", null);
		}
	}

	/**
	 * 
	 * @Title: doAdd
	 * @Description: 获取新增页面必要数据 success result
	 *               {"data":{"abbrevia":"AF","areaCname":"阿富汗"}} error result
	 *               {"isOk":0,"msg":"获取数据失败！"}
	 * @param request
	 * @param serviceObj
	 * @return 参数说明
	 * @return String 返回类型
	 * @author yeqingchao
	 * @date 2018年1月27日 下午11:03:34
	 */
	protected String doAdd(HttpServletRequest request, Object serviceObj) {
		try {
			Object bean = getParamBeanObject();
			return resultToJson(ResultCodeConstants.SUCCESS, "",
					getObjectBean(request, bean,  serviceObj, addFunctionName));
		} catch (Exception e) {
			return resultToJson(ResultCodeConstants.ERROR, "获取数据失败！", null);
		}
	}

	/**
	 * 
	 * @Title: doExport
	 * @Description: 导出
	 * @param request
	 * @param response
	 * @param serviceObj
	 *            接口对象
	 * @return void 返回类型
	 * @author yeqingchao
	 * @date 2018年1月31日 下午6:47:33
	 */
	@SuppressWarnings("unchecked")
	protected void doExport(HttpServletRequest request, HttpServletResponse response, Object serviceObj) {
		Object objectBean = null;
		try {
			objectBean = getParamBeanObject();
			objectBean = getBean(request, objectBean);
			Map<String, Object> excelDataMap = (Map<String, Object>) BaseUtil
					.getMethodFunction(exportFunctionName, serviceObj).invoke(serviceObj, objectBean);
			List<String> coulumNameList = (List<String>) excelDataMap.get("coulumNameList");
			List<List<Object>> excelList = (List<List<Object>>) excelDataMap.get("excelList");
			HSSFWorkbook workbook = ExportExcelUtil.export(coulumNameList, excelList);
			BaseUtil.downloadExcel(response, workbook);
		} catch (Exception e) {
			toResponseFunction(ResultCodeConstants.SUCCESS, "导出失败！", null, response);
		}
	}
	
	/**
	 * 共用返回方法
	 * 
	 * @Title: toResponseFunction
	 * @Description: TODO(共用返回方法)
	 * @param code_value
	 *            返回状态
	 * @param msg_str
	 *            返回消息
	 * @param t_data
	 *            返回结果
	 * @param response
	 *            参数说明
	 * @return void 返回类型
	 * @author TQ
	 * @date 2017年5月26日 下午3:25:17
	 */
	protected void toResponseFunction(int code_value, String msg_str, Object t_data, HttpServletResponse response) {
		Map<String, Object> result_bean = new HashMap<String, Object>();
		result_bean.put(ResultCodeConstants.CODE_NAME, code_value);
		result_bean.put(ResultCodeConstants.MSG_NAME, msg_str);
		result_bean.put(ResultCodeConstants.RESULT_NAME, t_data);
		AjaxUtil.writeString2Front(response, result_bean);
	}


	/**
	 * 
	 * @Title: doImport
	 * @Description: 导入excel success result {"isOk":1,"msg":"导入成功！"} error result
	 *               {"isOk":0,"msg":"导入失败！"}
	 * @param myfile
	 * @param serviceObj
	 * @return 参数说明
	 * @return String 返回类型
	 * @author yeqingchao
	 * @date 2018年2月2日 上午12:25:33
	 */
	@SuppressWarnings("unchecked")
	protected String doImport(HttpServletRequest request, MultipartFile myfile, Object serviceObj) {
		List<Map<String, Object>> importDatalist = null;
		try {
//			User user = getUser(request);
			importDatalist = ImportExcelUntil.importExcel(myfile);
			Map<String, Object> msgMap = (Map<String, Object>) BaseUtil
					.getMethodFunction(importFunctionName, serviceObj).invoke(serviceObj, importDatalist);
			if (msgMap == null) {
				return resultToJson(ResultCodeConstants.ERROR, "导入失败！", null);
			}
			int code = (int) msgMap.get(ExceptionConstants.RESULT_STATUC_CODE);
			String msg = (String) msgMap.get(ExceptionConstants.RESULT_MSG_CODE);
			return resultToJson(code, msg, null);
		} catch (Exception e) {
			return resultToJson(ResultCodeConstants.ERROR, "导入失败！", null);
		}
	}

	/**
	 * 
	 * @Title: doExportError
	 * @Description: 导入出错，导出原数据并加上错误明细
	 * @param request
	 *            参数说明
	 * @return void 返回类型
	 * @author yeqingchao
	 * @date 2018年2月2日 下午1:57:09
	 */
	protected void doExportError(HttpServletRequest request, HttpServletResponse response) {
//		String userName = getUser(request).getUserName();
//		HSSFWorkbook workbook = redisClient.getPojo(userName + ResultCodeConstants._EXCEL);
		HSSFWorkbook workbook=null;
		BaseUtil.downloadExcel(response, workbook);
	}

	// 获取方法返回值
	protected Object getObjectBean(HttpServletRequest request, Object objectBean, Object serviceObj,
			String methodName) throws Exception {
		Object object = null;
		objectBean = getBean(request, objectBean);
		Method[] methods = serviceObj.getClass().getMethods();
		for (Method method : methods) {
			if (method.getName().equals(methodName)) {
//				if (user == null) {
					object = method.invoke(serviceObj, objectBean);
//				} else {
//					object = method.invoke(serviceObj, objectBean, user);
//				}
				break;
			}
		}
		return object;
	}

	/*
	 * 将request参数封装进bean
	 */
	public Object getBean(HttpServletRequest request, Object objectBean) {
		Map<String, String> paraMap = RequestToBean.assembleRequestParam(request);
		if (paraMap != null && paraMap.size() > 0) {
			objectBean = JSON.parseObject(JSON.toJSONString(paraMap), objectBean.getClass());
		}
		return objectBean;
	}
//
//	/**
//	 * 获取当前用户对象
//	 */
//	protected User getUser(HttpServletRequest request) {
//		User user = null;
//		if (UserStore.get(request) != null) {
//			user = UserStore.get(request);
//		}
//		return user;
//	}

}
